﻿#pragma once
#include "XyNet/Common/Exception.h"
#include "XyNet/Common/Singleton.h"
#include "XyNet/Common/System.h"

namespace XyNet
{
	/// 跨语言交叉对象持有者
	template <typename ObjectType>
	class CrossObjectHolder : public Singleton<CrossObjectHolder<ObjectType>>
	{
	public:
#ifdef XYNET_PLATFORM_WINDOWS
		CrossObjectHolder()
		{
			try
			{
				if (_leakLogPath.isEmpty())
					_leakLogPath = System::getLogPath() / "Leak.log";
				if (FileSystem::isExists(_leakLogPath))
					FileSystem::remove(_leakLogPath);
			}
			catch (const exception& e)
			{
				HandleException(e);
			}
		}

		~CrossObjectHolder()
		{
			try
			{
				remove(nullptr);
				if (!_objectMap.empty())
				{
					auto text = string(typeid(this).name()) +
						" 未完全释放，剩余尺寸: " + lexical_cast<string>(_objectMap.size());
					FileSystem::File::appendText(_leakLogPath, text);
				}
				if (!_needRemoveObjects.empty())
				{
					auto text = string(typeid(this).name()) +
						" 错误的释放请求，数量: " +
						lexical_cast<string>(_needRemoveObjects.size());
					FileSystem::File::appendText(_leakLogPath, text);
				}
			}
			catch (const exception& e)
			{
				HandleException(e);
			}
		}
#endif

		ObjectType* add(shared_ptr<ObjectType> object)
		{
			try
			{
				//unique_lock<mutex> lock(_mutex);
				auto result = _objectMap.insert(make_pair(object.get(), object));
				assert(result.second && "Add object failed.");
				return object.get();
			}
			catch (const exception& e)
			{
				HandleException(e);
				return nullptr;
			}
		}

		void remove(ObjectType* object)
		{
			try
			{
				//unique_lock<mutex> lock(_mutex);
				if (object)
					_needRemoveObjects.insert(object);

				auto iter = Iterator<ObjectType*>::makeContainerIterator(&_needRemoveObjects);
				while (iter.moveNext())
				{
					auto obj = iter.getCurrent();
					auto iterator = _objectMap.find(obj);
					if (iterator != _objectMap.end())
					{
						_objectMap.erase(iterator);
						iter.removeCurrent();
					}
				}
			}
			catch (const exception& e)
			{
				HandleException(e);
			}
		}

		shared_ptr<ObjectType> get(ObjectType* object)
		{
			try
			{
				//unique_lock<mutex> lock(_mutex);
				auto iterator = _objectMap.find(object);
				assert(iterator != _objectMap.end() && "Can not find object.");
				return iterator->second;
			}
			catch (const exception& e)
			{
				HandleException(e);
				return nullptr;
			}
		}

	private:
		map<ObjectType*, shared_ptr<ObjectType>> _objectMap;	// 用裸指针做key，不适合用set
		set<ObjectType*> _needRemoveObjects;
		//mutex _mutex;

#ifdef XYNET_PLATFORM_WINDOWS
		FileSystem::Path _leakLogPath;
#endif
	};
}

//////////////////////////////////////////////////////////////////////////

namespace XyNet
{
	extern "C"
	{
		/// 持有字符串
		XYNET_API string* StringHold(const string& str);
		/// 创建字符串
		XYNET_API string* StringCreate(byte* bytes, int length);
		/// 销毁字符串
		XYNET_API void StringDestroy(string* str);
		/// 获取字符串长度
		XYNET_API int StringGetLength(string* str);
		/// 获取字符串数据
		XYNET_API void StringGetData(string* str, byte* outBytes);

		//////////////////////////////////////////////////////////////////////////

		/// 持有字节串
		XYNET_API Bytes* BytesHold(const Bytes& bytes);
		/// 创建字节串
		XYNET_API Bytes* BytesCreate(byte* bytes, int length);
		/// 销毁字节串
		XYNET_API void BytesDestroy(Bytes* bytes);
		/// 获取字节串长度
		XYNET_API int BytesGetLength(Bytes* bytes);
		/// 获取字节串数据
		XYNET_API void BytesGetData(Bytes* bytes, byte* outBytes);

		//////////////////////////////////////////////////////////////////////////

		/// 持有字节串向量
		XYNET_API vector<Bytes>* BytesVectorHold(const vector<Bytes>& bytess);
		/// 销毁字节串向量
		XYNET_API void BytesVectorDestroy(vector<Bytes>* bytess);
		/// 获取字节串向量长度
		XYNET_API int BytesVectorGetLength(vector<Bytes>* bytess);
		/// 获取字节串向量数据
		XYNET_API int BytesVectorGetBytesLength(vector<Bytes>* bytess, int index);
		/// 获取字节串向量数据
		XYNET_API void BytesVectorGetBytesData(
			vector<Bytes>* bytess, int index, byte* outBytes);

		//////////////////////////////////////////////////////////////////////////

		/// 创建指针向量
		XYNET_API vector<void*>* PointerVectorCreate();
		/// 销毁指针向量
		XYNET_API void PointerVectorDestroy(vector<void*>* v);
		/// 指针向量添加指针
		XYNET_API void PointerVectorAdd(vector<void*>* v, void* pointer);
	}
}